﻿using Masuit.Tools;

//以下大部分代码copy自国东

namespace SimpleX.RBAC
{
    public class SysOrgService : DbRepository<SysOrg>, ISysOrgService
    {
        public async Task<SqlSugarPagedList<SysOrg>> Page(SysOrgPageInput input)
        {
            var query = Context.Queryable<SysOrg>()
                             .WhereIF(!string.IsNullOrEmpty(input.ParentId), it => it.ParentId == input.ParentId)//父级
                             .WhereIF(input.OrgIds != null, it => input.OrgIds.Contains(it.Id))//机构ID查询
                             .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Name.Contains(input.SearchKey))//根据关键字查询
                             .OrderByIF(!string.IsNullOrEmpty(input.SortField), $"{input.SortField} {input.SortOrder}")
                             .OrderBy(it => it.SortCode);//排序
            var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
            return pageInfo;
        }

        public async Task<List<SysOrg>> Tree(List<string> orgIds = null)
        {
            //获取所有组织
            var sysOrgs = await GetListAsync();
            if (orgIds != null)
                sysOrgs = GetParentListByIds(sysOrgs, orgIds);//如果组织ID不为空则获取组织ID列表的所有父节点
            sysOrgs = sysOrgs.OrderBy(it => it.SortCode).ToList();//排序
                                                                  //构建组织树
            var result = ConstrucOrgTrees(sysOrgs);
            return result;
        }

        public List<SysOrg> GetParentListByIds(List<SysOrg> allOrgList, List<string> orgIds)
        {
            HashSet<SysOrg> sysOrgs = new HashSet<SysOrg>();//结果列表
                                                            //遍历组织ID
            orgIds.ForEach(it =>
            {
                //获取该组织ID的所有父级
                var parents = GetOrgParents(allOrgList, it);
                sysOrgs.AddRange(parents);//添加到结果
            });
            return sysOrgs.ToList();
        }

        public List<SysOrg> GetOrgParents(List<SysOrg> allOrgList, string orgId, bool includeSelf = true)
        {
            //找到组织
            var sysOrgs = allOrgList.Where(it => it.Id == orgId).FirstOrDefault();
            if (sysOrgs != null)//如果组织不为空
            {
                var data = new List<SysOrg>();
                var parents = GetOrgParents(allOrgList, sysOrgs.ParentId, includeSelf);//递归获取父节点
                data.AddRange(parents);//添加父节点;
                if (includeSelf)
                    data.Add(sysOrgs);//添加到列表
                return data;//返回结果
            }
            return new List<SysOrg>();
        }

        public List<SysOrg> ConstrucOrgTrees(List<SysOrg> orgList, string parentId = "0")
        {
            //找下级字典ID列表
            var orgs = orgList.Where(it => it.ParentId == parentId).OrderBy(it => it.SortCode).ToList();
            if (orgs.Count > 0)//如果数量大于0
            {
                var data = new List<SysOrg>();
                foreach (var item in orgs)//遍历字典
                {
                    item.Children = ConstrucOrgTrees(orgList, item.Id);//添加子节点
                    data.Add(item);//添加到列表
                }
                return data;//返回结果
            }
            return new List<SysOrg>();
        }

        public async Task Add(SysOrgAddInput input, string name = SimpleXConst.SysOrg)
        {
            var check = await CheckInput(input, name);//检查参数
            if (check != "OK")
            {
                Unify.SetError(check);
                return;
            }
            var sysOrg = input.Adapt<SysOrg>();//实体转换
            await InsertAsync(sysOrg);
        }

        public async Task Edit(SysOrgEditInput input, string name = SimpleXConst.SysOrg)
        {
            var check = await CheckInput(input, name);//检查参数
            if (check != "OK")
            {
                Unify.SetError(check);
                return;
            }

            var sysOrg = input.Adapt<SysOrg>();//实体转换
            await UpdateAsync(sysOrg);
        }

        public async Task Delete(List<BaseIdInput> input, string name = SimpleXConst.SysOrg)
        {
            //获取所有ID
            var ids = input.Select(it => it.Id).ToList();
            if (ids.Count > 0)
            {
                var sysOrgs = await GetListAsync();//获取所有组织
                var sysDeleteOrgList = new List<string>();//需要删除的组织ID集合
                ids.ForEach(it =>
                {
                    var childen = GetSysOrgChilden(sysOrgs, it);//查找下级组织
                    sysDeleteOrgList.AddRange(childen.Select(it => it.Id).ToList());
                    sysDeleteOrgList.Add(it);
                });
                //如果组织下有用户则不能删除
                if (await Context.Queryable<SysUser>().AnyAsync(it => sysDeleteOrgList.Contains(it.OrgId)))
                {
                    Unify.SetError($"请先删除{name}下的用户");
                    return;
                }

                //删除组织
                await DeleteByIdsAsync(sysDeleteOrgList.Cast<object>().ToArray());
            }
        }

        /// <summary>
        /// 检查输入参数
        /// </summary>
        /// <param orgName="sysOrg"></param>
        /// <param orgName="name">名称</param>
        private async Task<string> CheckInput(SysOrg sysOrg, string name)
        {
            //判断分类是否正确
            if (sysOrg.Category != CateGoryConst.Org_COMPANY && sysOrg.Category != CateGoryConst.Org_DEPT)
                return ($"{name}所属分类错误:{sysOrg.Category}");

            var sysOrgs = await GetListAsync();//获取全部
            if (sysOrgs.Any(it => it.ParentId == sysOrg.ParentId && it.Name == sysOrg.Name && it.Id != sysOrg.Id))//判断同级是否有名称重复的
                return ($"存在重复的同级{name}:{sysOrg.Name}");

            if (sysOrg.ParentId != SimpleXConst.Zero)
            {
                //获取父级,判断父级ID正不正确
                var parent = sysOrgs.Where(it => it.Id == sysOrg.ParentId).FirstOrDefault();
                if (parent != null)
                {
                    if (parent.Id == sysOrg.Id)
                        return ($"上级{name}不能选择自己");
                }
                else
                {
                    return ($"上级{name}不存在:{sysOrg.ParentId}");
                }
                sysOrg.Names = GetNames(sysOrgs, sysOrg.ParentId, sysOrg.Name);
            }

            return "OK";
        }

        public string GetNames(List<SysOrg> sysOrgs, string parentId, string orgName)
        {
            var names = "";
            //获取父级菜单
            var parents = GetOrgParents(sysOrgs, parentId, true);
            parents.ForEach(it => names += $"{it.Name}/");//循环加上名称
            names = names + orgName;//赋值全称
            return names;
        }

        public List<SysOrg> GetSysOrgChilden(List<SysOrg> orgList, string parentId)
        {
            //找下级组织ID列表
            var orgs = orgList.Where(it => it.ParentId == parentId).ToList();
            if (orgs.Count > 0)//如果数量大于0
            {
                var data = new List<SysOrg>();
                foreach (var item in orgs)//遍历组织
                {
                    var childen = GetSysOrgChilden(orgList, item.Id);//获取子节点
                    data.AddRange(childen);//添加子节点);
                    data.Add(item);//添加到列表
                }
                return data;//返回结果
            }
            return new List<SysOrg>();
        }

        public async Task<List<string>> GetOrgChildIds(string orgId, bool isContainOneself = true)
        {
            var orgIds = new List<string>();//组织列表
            if (!string.IsNullOrEmpty(orgId))//如果orgid有值
            {
                //获取所有子集
                var sysOrgs = await GetChildListById(orgId, isContainOneself);
                orgIds = sysOrgs.Select(x => x.Id).ToList();//提取ID列表
            }
            return orgIds;
        }

        public async Task<List<SysOrg>> GetChildListById(string orgId, bool isContainOneself = true)
        {
            //获取所有组织
            var sysOrgs = await GetListAsync();
            //查找下级
            var childLsit = GetSysOrgChilden(sysOrgs, orgId);
            if (isContainOneself)//如果包含自己
            {
                //获取自己的组织信息
                var self = sysOrgs.Where(it => it.Id == orgId).FirstOrDefault();
                if (self != null) childLsit.Insert(0, self);//如果组织不为空就插到第一个
            }
            return childLsit;
        }
    }
}